import com.alibaba.fastjson.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * 代理类
 * @author ykw
 * 2020/11/12
 */
public class HotSwapAgent {

    public static void agentmain(String paramMap, Instrumentation inst) throws Exception {
        JSONObject jsonObject = JSONObject.parseObject(paramMap);
        String classPath = jsonObject.getString("classFilePath");
        String replaceClassNameSet = jsonObject.getString("classNameSet");
        System.out.println("agent start....args = " + paramMap);
        HashSet<String> nameSet = JSONObject.parseObject(replaceClassNameSet, HashSet.class);
        List<String> failClassNameList = new ArrayList<String>();
        Class<?>[] allClass = inst.getAllLoadedClasses();

        for(Class<?> c : allClass) {
            if (nameSet.contains(c.getName())) {
                String[] nameArr = c.getName().split("\\.");
                String simplifiedName = nameArr[nameArr.length - 1];
                String pathname = classPath + simplifiedName + ".class";
                File file = new File(pathname);

                try {
                    byte[] bytes = fileToBytes(file);
                    ClassDefinition classDefinition = new ClassDefinition(c, bytes);
                    inst.redefineClasses(classDefinition);
                    System.out.println(c.getName() + " update success");
                } catch (IOException var19) {
                    var19.printStackTrace();
                    System.out.println(c.getName() + " update fail");
                    failClassNameList.add(c.getName());
                }
            }
        }

        System.out.println("hot update finish...");
        if (!failClassNameList.isEmpty()) {
            System.out.println("update fail class list - >" + JSONObject.toJSONString(failClassNameList));
        }

    }

    public static byte[] fileToBytes(File file) throws IOException {
        FileInputStream in = new FileInputStream(file);
        byte[] bytes = new byte[in.available()];
        in.read(bytes);
        in.close();
        return bytes;
    }
}
